package com.zmzncs.lmtc.module.promotion.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmzncs.lmtc.common.pojo.daoer.MonthAmount;
import com.zmzncs.lmtc.common.pojo.tengda.CarTypes;
import com.zmzncs.lmtc.common.util.*;
import com.zmzncs.lmtc.module.customer.dao.CardDao;
import com.zmzncs.lmtc.module.park.dao.ParkInfoDao;
import com.zmzncs.lmtc.module.promotion.dao.MonthRuleFeeScaleMapper;
import com.zmzncs.lmtc.module.promotion.dao.MonthRuleMapper;
import com.zmzncs.lmtc.module.promotion.dao.MonthRuleParkMapper;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule.MonthRule;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule.MonthRuleDTO;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule_fee_scale.MonthRuleFeeScale;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule_fee_scale.MonthRuleFeeScaleDTO;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule_park.MonthRulePark;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule_park.MonthRuleParkDTO;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule_pull.*;
import com.zmzncs.lmtc.module.promotion.dao.MonthRulePullDao;
import com.zmzncs.lmtc.module.park.pojo.park_info.ParkInfo;
import com.zmzncs.lmtc.module.promotion.service.MonthRulePullService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zmzncs.lmtc.module.system.pojo.user.UserLoginVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparingLong;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 直联车场-月租规则 服务实现类
 * </p>
 *
 * @author 高博文
 * @since 2021-03-19
 */
@Service
public class MonthRulePullServiceImpl extends ServiceImpl<MonthRulePullDao, MonthRulePull> implements MonthRulePullService {

    @Autowired
    ParkInfoDao parkInfoDao;
    @Autowired
    MonthRulePullDao monthRulePullDao;
    @Autowired
    MonthRuleMapper monthRuleMapper;
    @Autowired
    MonthRuleParkMapper monthRuleParkMapper;
    @Autowired
    MonthRuleFeeScaleMapper monthRuleFeeScaleMapper;
    @Autowired
    CardDao cardDao;


    @Autowired
    HttpServletRequest request;


    @Async("threadPoolExecutor")
    @Override
    public Map<String,String> getMonthRule(Long parkInfoId,String daoerParkId) {

        Map<String,String> map = new HashMap();
        ParkInfo parkInfo = parkInfoDao.selectById(parkInfoId);
        if (parkInfo == null){
            ExceptionUtil.businessException("停车场数据不存在");
        }

        //获取道尔月租费率
        MonthAmount monthAmount = DaoerApiUtil.getMonthAmount(daoerParkId,parkInfo.getDaoerSecretKey());

        if (monthAmount == null || monthAmount.getHead().getStatus().equals(0) || monthAmount.getBody() == null || monthAmount.getBody().isEmpty()) {
            ExceptionUtil.businessException("获取停车场月租信息失败");
        }

        //根据停车场ID查询道尔月租规则信息
        for (MonthAmount.Body daoerMonth : monthAmount.getBody()) {
            BigDecimal amount = new BigDecimal(daoerMonth.getPackageCharge());
            MonthRulePull month = new MonthRulePull();
            month.setParkId(parkInfoId);
            month.setMonthType(daoerMonth.getPackageType().toString());
            month.setDurationType(daoerMonth.getPackageDuration().toString());
            month.setParkAmount(amount);
            month.setRemark(daoerMonth.getRemark());
            month.setMonthName(daoerMonth.getPackageName());
            month.setParkSource(3);
            month.setStatus(1);

            List<MonthRulePullDTO> monthRulePullDTOList = monthRulePullDao.getMonthRulePullByParkInfoId(parkInfoId);
            if (monthRulePullDTOList != null && monthRulePullDTOList.size() > 0){
                monthRulePullDao.deleteByParkId(parkInfoId);
            }
            monthRulePullDao.insert(month);
        }
        map.put("status", "1");
        map.put("msg", "获取道尔停车场月租信息成功");
        return map;
    }

    @Override
    public IPage<MonthRulePullTableVO> getMonthRuleGroupByPark(Integer page,Integer size,String parkName) {
        if (page == null){
            page = 1;
        }
        if (size == null){
            size = 10;
        }
        Page<Object> objectPage = new Page<>(page, size);
        //查询月租规则的停车场信息
        IPage<MonthRulePullTableVO> iPage =  monthRulePullDao.getMonthRuleParkName(objectPage,parkName);
        if (iPage != null && iPage.getRecords() != null && iPage.getRecords().size() > 0){
            List<MonthRulePullTableVO> records = iPage.getRecords();
            for (MonthRulePullTableVO record : records) {
                Long mwMonthCustCount = cardDao.getMWMonthCustCount(record.getParkId());
                record.setMonthCarCount(mwMonthCustCount);
            }
        }

        return iPage;
    }

    @Override
    public List<MonthRulePullDTO> getParkMonthRuleByParkId(Long parkId) {
        //获取车场拉取的最新月租规则
        List<MonthRulePullDTO> monthRulePullDTOS = monthRulePullDao.getNewMonthRule(parkId);
        //获取停车场已经设置修改过的月租信息
        List<MonthRuleDTO> monthRuleDTOList = monthRuleFeeScaleMapper.getMonthRuleByParkId(parkId);
        //  根据park_id查询
        MonthRuleParkDTO monthRuleParkDTO = monthRuleParkMapper.getByParkId(parkId);

        if (monthRuleDTOList != null && monthRuleDTOList.size() > 0){
            for (MonthRulePullDTO pull : monthRulePullDTOS) {
                for (MonthRuleDTO rule : monthRuleDTOList) {
                    if (pull.getId().equals(rule.getMonthRulePullId())) {
                        pull.setRuleId(monthRuleParkDTO.getMonthRuleId());
                        pull.setParkId(parkId);
                        pull.setFeeScaleId(rule.getFeeScaleId());
                        pull.setMonthRentName(rule.getMonthRentName());
                        pull.setMarketingMonthCode(rule.getMonthRentType().toString());
                        pull.setParkAmount(rule.getParkAmount());
                        pull.setBeginTime(rule.getBeginTime());
                        pull.setEndTime(rule.getEndTime());
                        pull.setClientStatus(rule.getClientStatus());
                        pull.setOwnerStatus(rule.getOwnerStatus());
                        pull.setDays(rule.getDays());
                        pull.setAmount(rule.getAmount());
                        pull.setUniformRentType(rule.getUniformRentType());
                        pull.setParkSource(4);
                    }
                }
            }
        }

        return monthRulePullDTOS;
    }

    /**
     * 添加月租规则
     */
    @Override
    @Transactional
    public void addMonthRule(MonthRulePullAddForm form) {
        UserLoginVO loginUser = JwtUtil.getLoginUser(request);
        Long monthRuleId;
        //  根据park_id查询
        MonthRuleParkDTO monthRuleParkDTO = monthRuleParkMapper.getByParkId(form.getParkId());
        if(monthRuleParkDTO == null){
            ParkInfo parkInfo = parkInfoDao.selectById(form.getParkId());

            //  添加月租规则
            MonthRule monthRule = new MonthRule();
            BeanUtils.copyProperties(form, monthRule);
            monthRule.setRuleName(parkInfo.getParkName() + "月租规则");
            monthRule.setCreateUserId(loginUser.getUserId());
            monthRule.setStatus(1);
            monthRuleMapper.insert(monthRule);
            monthRuleId = monthRule.getId();

            //  月租规则关联停车场
            MonthRulePark monthRulePark = new MonthRulePark();
            monthRulePark.setParkId(form.getParkId());
            monthRulePark.setMonthRuleId(monthRule.getId());
            monthRuleParkMapper.insert(monthRulePark);
        } else {
            monthRuleId = monthRuleParkDTO.getMonthRuleId();
        }

        MonthRuleFeeScaleDTO monthRuleFeeScaleDTO = monthRuleFeeScaleMapper.getByMonthRentType(monthRuleId, form.getMonthType());
        if(monthRuleFeeScaleDTO != null){
            ExceptionUtil.businessException("收费标准已经存在，请请求修改接口");
        }

        //  月租收费规则
        MonthRuleFeeScale feeScale = new MonthRuleFeeScale();
        feeScale.setMonthRuleId(monthRuleId);
        feeScale.setMonthRentType(form.getMonthType());
        feeScale.setMonthRentName(form.getMonthRentName());
        feeScale.setAmount(form.getAmount());
        feeScale.setParkAmount(form.getParkAmount());
        feeScale.setDays(form.getDays());
        feeScale.setMonthRulePullId(form.getPullId());
        feeScale.setUniformRentType(form.getUniformRentType());
        feeScale.setClientStatus(form.getClientStatus());
        feeScale.setOwnerStatus(form.getOwnerStatus());
        feeScale.setBeginTime(form.getBeginTime());
        feeScale.setEndTime(form.getEndTime());
        monthRuleFeeScaleMapper.insert(feeScale);

    }

    @Override
    public void updateParkMonthRule(Long parkId) {
        ParkInfo parkInfo = parkInfoDao.selectById(parkId);
        if (parkInfo == null){
            ExceptionUtil.businessException("停车场不存在，parkId:" + parkId);
        }

        List<MonthRulePull> newMonthRule = new ArrayList<>();
        List<MonthRulePullDTO> oldMonthRule = monthRulePullDao.getMonthRulePullByParkInfoId(parkId);

        Integer parkSource = parkInfo.getParkSource();

        //道尔
        if (parkSource.equals(3)){

            MonthAmount monthAmount = DaoerApiUtil.getMonthAmount(parkInfo.getBolianParkId(),parkInfo.getDaoerSecretKey());

            if (monthAmount == null || monthAmount.getHead().getStatus().equals(0) || monthAmount.getBody() == null || monthAmount.getBody().isEmpty()) {
                ExceptionUtil.businessException("获取停车场月租信息失败");
            }

            //根据停车场ID查询道尔月租规则信息
            for (MonthAmount.Body daoerMonth : monthAmount.getBody()) {
                BigDecimal amount = new BigDecimal(daoerMonth.getPackageCharge());
                MonthRulePull month = new MonthRulePull();
                month.setParkId(parkId);
                month.setMonthType(daoerMonth.getPackageType().toString());
                month.setDurationType(daoerMonth.getPackageDuration().toString());
                month.setParkAmount(amount);
                month.setRemark(daoerMonth.getRemark());
                month.setMonthName(daoerMonth.getPackageName());
                month.setParkSource(3);

                newMonthRule.add(month);
            }
        }

        //腾达
        if (parkSource.equals(4)){

            //查询所有车辆类型
            List<CarTypes> carTypes = TengdaUtil.getCarTypes(parkInfo.getBolianParkId());
            if (carTypes == null || carTypes.size() < 1) {
                ExceptionUtil.businessException("从腾达获取车辆类型信息失败，bolianParkId：" + parkInfo.getBolianParkId());
            }

            for (CarTypes carType : carTypes) {
                if (carType.getCode() > 80 && carType.getCode() != 91) {
                    MonthRulePull month = new MonthRulePull();
                    month.setParkId(parkInfo.getId());
                    month.setMonthType(carType.getCode().toString());
                    month.setDurationType("1");
                    month.setMonthName(carType.getName());
                    month.setParkAmount(new BigDecimal(0));
                    month.setRemark("");
                    month.setParkSource(4);

                    newMonthRule.add(month);
                }
            }
        }

        if (newMonthRule != null && newMonthRule.size() > 0){
            if (oldMonthRule != null && oldMonthRule.size() > 0){
                List<MonthRulePull> monthRulePulls = JsonUtil.listTransform(oldMonthRule, MonthRulePull.class);
                //处理更新后的车场拉取的月租规则信息
                updateNewMonthRulePull(monthRulePulls,newMonthRule);
            } else {
                for (MonthRulePull rulePull : newMonthRule) {
                    monthRulePullDao.insert(rulePull);
                }
            }
        } else {
            ExceptionUtil.businessException("停车场暂无更新月租规则");
        }
    }

    /**
     * 处理更新后的车场拉取的月租规则信息
     * */

    public void updateNewMonthRulePull(List<MonthRulePull> oldList,List<MonthRulePull> newList){

        List<String> newTypes = newList.stream().map(MonthRulePull::getMonthType).collect(toList());
        List<String> oldTypes = oldList.stream().map(MonthRulePull::getMonthType).collect(toList());

        //正常
        List<String> shareTypes = oldTypes.stream().filter(newTypes::contains).collect(toList());
        //删除(oldTypes)
        oldTypes.removeAll(shareTypes);
        //新增(newTypes)
        newTypes.removeAll(shareTypes);

        List<MonthRulePull> allList = new ArrayList<>();
        allList.addAll(oldList);
        allList.addAll(newList);

        oldList.clear();
        newList.clear();

        for (MonthRulePull pull : allList) {
            //删除状态
            for (String oldType : oldTypes) {
                if (pull.getMonthType().equals(oldType)){
                    pull.setStatus(2);
                    oldList.add(pull);
                }
            }
            //新增状态
            for (String newType : newTypes) {
                if (pull.getMonthType().equals(newType)){
                    pull.setStatus(3);
                    newList.add(pull);
                }
            }
        }

        if (oldList != null && oldList.size() > 0){
            List<MonthRulePull> unique = oldList.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MonthRulePull::getRemark))), ArrayList::new));
            for (MonthRulePull rulePull : unique) {
                monthRulePullDao.updateById(rulePull);
            }
        }

        if (newList != null && newList.size() > 0){
            List<MonthRulePull> unique = newList.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MonthRulePull::getRemark))), ArrayList::new));
            for (MonthRulePull rulePull : unique) {
                monthRulePullDao.insert(rulePull);
            }
        }




    }

    /**
     * 编辑月租规则
     */
    @Override
    @Transactional
    public void updateMonthRule(MonthRulePullUpdateForm form) {
        MonthRuleFeeScale monthRuleFeeScale = monthRuleFeeScaleMapper.selectById(form.getFeeScaleId());
        List<MonthRuleFeeScaleDTO> monthRuleFeeScaleList = monthRuleFeeScaleMapper.getMonthRuleFeeScaleByRuleId(form.getRuleId());
        List<Integer> uniformRentTypeList = monthRuleFeeScaleList.stream().map(MonthRuleFeeScaleDTO::getUniformRentType).collect(Collectors.toList());
        //  如果收费标准已存在，并且不是当前收费标准
        if(uniformRentTypeList.contains(form.getUniformRentType()) && !form.getUniformRentType().equals(monthRuleFeeScale.getUniformRentType())){
            ExceptionUtil.businessException("配置规则【" + form.getMonthRentName() + "】已存在，请选择其他匹配规则");
        }

        MonthRuleFeeScale feeScale = new MonthRuleFeeScale();
        feeScale.setMonthRuleId(form.getRuleId());
        feeScale.setMonthRentType(form.getMonthType());
        feeScale.setMonthRentName(form.getMonthRentName());
        feeScale.setAmount(form.getAmount());
        feeScale.setParkAmount(form.getParkAmount());
        feeScale.setDays(form.getDays());
        feeScale.setMonthRulePullId(form.getPullId());
        feeScale.setUniformRentType(form.getUniformRentType());
        feeScale.setClientStatus(form.getClientStatus());
        feeScale.setOwnerStatus(form.getOwnerStatus());
        feeScale.setId(form.getFeeScaleId());
        feeScale.setBeginTime(form.getBeginTime());
        feeScale.setEndTime(form.getEndTime());
        monthRuleFeeScaleMapper.updateById(feeScale);

        MonthRule monthRule = new MonthRule();
        monthRule.setId(form.getRuleId());
        monthRule.setRuleName(form.getMonthRentName());
        monthRule.setStatus(form.getClientStatus());
        monthRuleMapper.updateById(monthRule);

    }
}
